﻿using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;

namespace Abide.Classes
{
    public class AddOnManifest
    {
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        public string UpdateInfoUrl
        {
            get { return updateInfoUrl; }
            set { updateInfoUrl = value; }
        }
        public string PrimaryAssembly
        {
            get { return primaryAssembly; }
            set { primaryAssembly = value; }
        }
        public string[] FileNames
        {
            get { return fileNames; }
        }
        public string[] Directories
        {
            get { return directories; }
        }
        public AssemblyName AssemblyName
        {
            get { return assemblyName; }
            set { assemblyName = value; }
        }
        public Dropbox Dropbox
        {
            get { return dropBox; }
            set { dropBox = value; }
        }
        public string Root
        {
            get { return manifestRoot; }
            set { manifestRoot = value; }
        }

        private string name;
        private string updateInfoUrl;
        private string primaryAssembly;
        private string[] fileNames;
        private string[] directories;
        private AssemblyName assemblyName;
        private Dropbox dropBox;
        private string manifestRoot;

        public AddOnManifest()
        {
            this.fileNames = new string[0];
            this.directories = new string[0];
            this.updateInfoUrl = string.Empty;
        }

        public override string ToString()
        {
            return name;
        }
        public string GetSafeName()
        {
            //Return
            return this.name.Trim().Replace(" ", "_").Replace("<", "_").Replace(">", "_");
        }
        public void Load(string fileName)
        {
            //Read
            XmlDocument Document = new XmlDocument();
            Document.Load(fileName);

            //Grab Nodes
            XmlNode Manifest = Document["Manifest"];
            XmlNode Files = Manifest["Files"];
            XmlNode Directores = Manifest["Directories"];

            //Set
            this.fileNames = new string[0];
            this.directories = new string[0];
            this.updateInfoUrl = string.Empty;

            //Read Data
            name = Manifest["Name"].InnerText;
            updateInfoUrl = Manifest["UpdateInformationUrl"].InnerText;
            primaryAssembly = Manifest["PrimaryAssembly"].InnerText;
            for (int i = 0; i < Files.ChildNodes.Count; i++)
                AddFile(Files.ChildNodes[i].InnerText);
            for (int i = 0; i < Directores.ChildNodes.Count; i++)
                AddDirectory(Directores.ChildNodes[i].InnerText);
        }
        public void AddFile(string fileName)
        {
            List<string> fileNames = new List<string>(this.fileNames);
            fileNames.Add(fileName);
            this.fileNames = fileNames.ToArray();
        }
        public void AddFileRange(IEnumerable<string> fileNames)
        {
            List<string> newFileNames = new List<string>(this.fileNames);
            newFileNames.AddRange(fileNames);
            this.fileNames = newFileNames.ToArray();
        }
        public void AddDirectory(string directory)
        {
            List<string> directories = new List<string>(this.directories);
            directories.Add(directory);
            this.directories = directories.ToArray();
        }
        public void AddDirectoryRange(IEnumerable<string> directories)
        {
            List<string> newDirectories = new List<string>(this.directories);
            newDirectories.AddRange(directories);
            this.directories = newDirectories.ToArray();
        }
        public void Write(string fileName)
        {
            //Prepare
            using (FileStream fs = new FileStream(fileName, FileMode.Create))
            {
                //Setup XML writer settings
                XmlWriterSettings Settings = new XmlWriterSettings();
                Settings.Indent = true;
                Settings.Encoding = Encoding.UTF8;
                Settings.CloseOutput = true;

                //Create
                XmlWriter writer = XmlWriter.Create(fs, Settings);

                //Write Header
                writer.WriteStartDocument();

                //Write Manifest
                writer.WriteStartElement("Manifest");

                //Write Name
                writer.WriteStartElement("Name");
                writer.WriteValue(name);
                writer.WriteEndElement();

                //Write Update URL
                writer.WriteStartElement("UpdateInformationUrl");
                writer.WriteValue(updateInfoUrl);
                writer.WriteEndElement();

                //Write Primary Assembly
                writer.WriteStartElement("PrimaryAssembly");
                writer.WriteValue(primaryAssembly);
                writer.WriteEndElement();

                //Write FileNames
                writer.WriteStartElement("Files");
                foreach (string file in fileNames)
                {
                    //Write File
                    writer.WriteStartElement("File");
                    writer.WriteValue(file);
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();

                //Write Directories
                writer.WriteStartElement("Directories");
                foreach (string directory in directories)
                {
                    //Write Directory
                    writer.WriteStartElement("Directory");
                    writer.WriteValue(directory);
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();

                writer.WriteEndElement();

                writer.WriteEndDocument();

                //Close
                writer.Close();
            }
        }
    }
}
